import re
import fnmatch

from forest.resource import Resources, Resource
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)

COLORS = {
    'WARNING'  : YELLOW,
    'INFO'     : WHITE,
    'DEBUG'    : BLUE,
    'CRITICAL' : YELLOW,
    'ERROR'    : RED,
    'RED'      : RED,
    'GREEN'    : GREEN,
    'YELLOW'   : YELLOW,
    'BLUE'     : BLUE,
    'MAGENTA'  : MAGENTA,
    'CYAN'     : CYAN,
    'WHITE'    : WHITE,
}

RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
BOLD_SEQ  = "\033[1m"

'''
# stripping a package that was included (often by package resolution)
# Prefix the package name/glob with a minus.
- name: -packagename
'''
class Package(Resource):
    '''
        The following example shows the various ways packages can be specified::

            resources:
            # Individual packages can be specified as a simple list item
            - package(NetworkManager-gnome)

            # Repo groups can be specified
            - package(@gnome-desktop)

            - $: package
              name: mdadm
              erase: True

            # specific files can be removed from a package
            - $: package
              name: coreutils
              remove: [ list of files to strip from the package ]

            # OR a combination of include/exclude
            - $: package
              name: tzdata
              include:
              - /usr/share/zoneinfo/UTC

            - $: package
              name: mdadm
              exclude:
              - /lib/systemd/system/*
              - /etc/*
    '''
    __register__ = "package"

    def __init__(self, config, value):
        super(Package, self).__init__(config, value)

        if 'name' not in value:
            raise Exception("Package missing name")

    def get_id(self):
        return 'package:'+self.value.get('name')


class PackageAction(object):
    name = ''
    install = True
    removes = None
    includes = None
    excludes = None
    strip_entire = False
    group = False

    def get_name(self):
        return self.name

    def get_group_default(self):
        return self.group_default

    def get_group_optional(self):
        return self.group_optional


    def __init__(self, name=None, **kwargs):

        if name is not None:
            self.name = name

        self.removes = kwargs.get('remove', [])
        self.strip_entire = kwargs.get('erase', False)
        self.name = kwargs.get('name', name)
        self.group_default = kwargs.get('default', False)
        self.group_optional = kwargs.get('optional', False)

        if self.strip_entire:
            self.removes = ['*']

        if self.name[0] == '@':
            self.group = True

        self.includes = []

    def requires_erase(self):
        return self.strip_entire

    def get_removes(self):
        ''' Returns a list of regular expressions representing files to remove
            from the package.
        '''
        removes = []
        for g in self.removes:
            if g.startswith('RE '):
                g = g[3:]
                globs_re = re.compile(g)
            else:
                globs_re = re.compile(fnmatch.translate(g))

            removes.append(globs_re)
        return removes

    def get_name(self):
        return self.name

    def get_files(self):
        pass

    def __repr__(self):
        return 'PackageAction(%s%s%s, removes=%s%s%s, erase=%s)' % (
            BOLD_SEQ,
            self.name,
            RESET_SEQ,
            COLOR_SEQ % (30 + COLORS['RED']),
            self.removes,
            RESET_SEQ,
            self.requires_erase()
        )

    def is_group(self):
        return self.group

    def __hash__(self):
        return self.name

    def merge(self, other):
        self.excludes = other.excludes
        self.includes = other.excludes
        self.group = other.group
        return self

class PackageInstallList(object):
    def __init__(self, config):
        self.config = config
        self.actions = []
        self.resources = config.get_resources()
        self.process_packagelist()

    def process_packagelist(self, yumtool=None):
        ''' Builds a package action list '''
        self.actions = []

        # one pass to gather whats defined
        for package_resource in self.resources.iter_by_type("package"):
            pa = PackageAction(**package_resource.value)
            self.actions.append(pa)

        return self.actions

    def get_package(self, name):
        for action in self.actions:
            print 'Match', action.get_name(), name
            if action.get_name() == name:
                return action
        return None

    def __iter__(self):
        return iter(self.actions)

    def __getitem__(self, index):
        return self.actions[index]

    def __repr__(self):
        return "PackageInstallList(\n%s\n)" % ',\n'.join([repr(a) for a in self.actions])
